package com.sketch.commom.utils;


import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @Author zq
 * @Date 2018/12/26 19:25
 */
public class DateUtil {

    private static String[] dates = {"上午", "下午", "晚上"};

    private static final ZoneId ZONE = ZoneId.systemDefault();

    public static LocalDate getLocalDate(String date) {
        LocalDate ldt = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return ldt;
    }


    public static LocalDateTime getStart(String date) {
        LocalDate ldt = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDateTime localDateTime = ldt.atTime(0, 0, 0);
        return localDateTime;
    }
    public static Integer getTimeLong() {
        return (int) (System.currentTimeMillis() / 1000);
    }
    public static LocalDateTime getEnd(String date) {
        LocalDate ldt = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDateTime localDateTime = ldt.atTime(23, 59, 59);
        return localDateTime;
    }

    public static String getDateStr() {
        String str = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return str;
    }

    public static String getYesterDayStr() {
        String str = LocalDateTime.now().plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return str;
    }

    public static ZonedDateTime getStartDayTime(String date) {
        LocalDate localDate = getLocalDate(date);
        return localDate.atTime(0, 0, 0).atZone(ZoneId.systemDefault());
    }

    public static ZonedDateTime getEndDayTime(String date) {
        LocalDate localDate = getLocalDate(date);
        return localDate.atTime(23, 59, 59).atZone(ZoneId.systemDefault());
    }

    public static Date strToDate(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        ParsePosition pos = new ParsePosition(0);
        Date strtodate = formatter.parse(strDate, pos);
        return strtodate;
    }

    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime;
    }

    public static Long getTimeDifference(Date date) {
        Date now = new Date();
        return date.getTime() - now.getTime();
    }

    public static String localDateToString(LocalDate date) {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String dateStr = date.format(fmt);
        return dateStr;
    }

    public static String localDate2String(LocalDate date) {
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyyMMdd");
        String dateStr = date.format(fmt);
        return dateStr;
    }

    public static List<LocalDate> getList(Integer days) {
        List<LocalDate> localDateList = new ArrayList<>();
        for (int j = 1; j < days; j++) {
            LocalDate localDate = LocalDate.now().minusDays(j);
            localDateList.add(localDate);
        }
        return localDateList;
    }

    public static List<LocalDate> getTimeList(String startTime, String endTime) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate date = LocalDate.parse(startTime, dateTimeFormatter);
        LocalDate end = LocalDate.parse(endTime, dateTimeFormatter).minusDays(1);
        List<LocalDate> dateList = new ArrayList<>();
        while (!date.isAfter(end)) {
            dateList.add(date);
            date = date.plusDays(1);
        }
        return dateList;
    }

    public static LocalDate toLocalDate(String date) {
        LocalDate localDate = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return localDate;
    }

    public static List<LocalDate> getDatesBetweenUsingJava8(LocalDate startDate, LocalDate endDate) {
        long numOfDaysBetween = ChronoUnit.DAYS.between(startDate, endDate) + 1;
        return IntStream.iterate(0, i -> i + 1)
                .limit(numOfDaysBetween)
                .mapToObj(startDate::plusDays)
                .collect(Collectors.toList());
    }


    public static String getDateTimeStr() {
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        String time = df.format(new Date());
        return (time);
    }

    public static LocalDateTime timestamToDatetime(long timestamp) {
        Instant instant = Instant.ofEpochMilli(timestamp);
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    public static LocalDateTime toLocalDateTime(String date) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime ldt = LocalDateTime.parse(date, df);
        return ldt;
    }

    public static String getZonedDateTimetoString(ZonedDateTime zonedDateTime) {
        ZonedDateTime zoneDateTime1 = zonedDateTime.plusHours(11);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return zoneDateTime1.format(formatter);
    }

    public static String timeStamp2Date(String seconds) {
        if (seconds == null || seconds.isEmpty() || seconds.equals("null")) {
            return "";
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date(Long.valueOf(seconds)));
    }


    public static String getClock(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.HOUR_OF_DAY);
        if (w < 13 && w >= 4) {
            return dates[0];
        } else if (w >= 13 && w < 20) {
            return dates[1];
        }
        return dates[2];
    }

    /**
     * 获取时间戳ms
     */
    public static Long getTimeLong(Date date) {
        return date.getTime();
    }

    /**
     * 获取date对象
     */
    public static Date getDate(String date) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        if (date == null || date.equals("")) {
            return null;
        }
        try {
            return df.parse(date);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public static Integer getDayCha(String st, String et) {
        return Math.toIntExact((getTimeLong(getDate(et)) - getTimeLong(getDate(st))) / (1000 * 3600 * 24) + 1);
    }

    /**
     * 获取指定天数前0点时间
     *
     * @return
     */
    public static Date getAssignDayStart(Integer preious) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.set(Calendar.DATE, cal.get(Calendar.DATE) - preious);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }


    public static Integer getChaDay(Date st, Date et) {
        return Math.toIntExact((getTimeLong(et) - getTimeLong(st)) / 1000);
    }

    public static Date getMinusDaysTime(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        Date date = Date.from(zdt.toInstant());
        return date;
    }


    public static Date LocalDateToUdate(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * 获取一个月第一天的0时0分0秒
     *
     * @param date
     * @return
     */
    public static LocalDateTime getMonthStart(String date) {
        LocalDate ldt = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDate firstday = ldt.with(TemporalAdjusters.firstDayOfMonth());
        LocalDateTime localDateTime = firstday.atTime(0, 0, 0);
        return localDateTime;
    }

    /**
     * 获取一个月最后一天的23时59分59秒
     *
     * @param date
     * @return
     */
    public static LocalDateTime getMonthEnd(String date) {
        LocalDate ldt = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDate firstday = ldt.with(TemporalAdjusters.lastDayOfMonth());
        LocalDateTime localDateTime = firstday.atTime(23, 59, 59);
        return localDateTime;
    }

    public static void main(String[] args) {
        System.out.println(getEnd("2024-02-18"));
        System.out.println(timeStamp2Date("1563448403000"));
    }

    /**
     * LocalDate 转 LocalDateTime
     *
     * @param localDate
     * @return
     */
    public static LocalDateTime tranferLocalDateToLocalDateTime(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        return LocalDateTime.ofInstant(instant, zone);
    }

    /**
     * localDateTime 转 string
     *
     * @param localDateTime
     * @param format
     * @return
     */
    public static String localDateTimeToStr(LocalDateTime localDateTime, String format) {
        if (null == localDateTime || StringUtils.isBlank(format)) {
            return null;
        }
        DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
        return localDateTime.format(df);
    }

    public static Date localDate2Date(LocalDate localDate) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
        return Date.from(zdt.toInstant());
    }


    /**
     * 获取一周前的时间
     * @param localDateTime
     * @return
     */
    public static LocalDateTime getOneWeekBeforeTime(LocalDateTime localDateTime) {
        Calendar calendar = Calendar.getInstance();
        Date date = DateUtil.localDateTimeToDate(localDateTime);
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -7);
        Date beforeWeek = calendar.getTime();
        return dateToLocalDateTime(beforeWeek);
    }

    private static Date localDateTimeToDate(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        final ZoneId zoneId = ZoneId.systemDefault();
        final ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
        final Date date = Date.from(zonedDateTime.toInstant());
        return date;
    }
    public static Date getDefaultBirthday(){
        Calendar cal=Calendar.getInstance();
        cal.add(Calendar.YEAR,-20);
        return cal.getTime();
    }

}
